package bitetorrentserver;

import java.io.IOException;
import java.io.OutputStream;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

/**
 * Simple HTTP
 * @author user
 */
public class Tracker implements HttpHandler {

    PeerFileList peerFileList;
    static long timeout = 60000;
    static long delay = 500;
    static int port = 8080;

    public static void main(String[] args) throws IOException {
        String temp;
        Integer intTemp;

        // Get port if any
        if (args.length > 0) {
            temp = args[0];
            intTemp = Integer.getInteger(temp);

            if (intTemp != null) {
                port = intTemp;
            }
        }

        // Get interval if any
        if (args.length > 1) {
            temp = args[1];
            intTemp = Integer.getInteger(temp);

            if (intTemp != null) {
                timeout = intTemp;
            }
        }

        InetSocketAddress addr = new InetSocketAddress(port);
        HttpServer server = HttpServer.create(addr, 0);

        Tracker tracker = new Tracker();
        server.createContext("/", tracker);
        server.setExecutor(Executors.newCachedThreadPool());
        server.start();

        System.out.println("Server is listening on port " + port);

        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        String s = br.readLine();
        server.stop(0);

        tracker.peerFileList.listFiles.save();

        System.out.println("List files : \n" + tracker.peerFileList.listFiles);
    }

    public Tracker() {
        peerFileList = new PeerFileList();
    }

    public PeerFile parseQuery(Request getpar, HttpExchange exchange) {

        String str = "";
        PeerFile temp = new PeerFile();

        str = getpar.parameter.get("info_hash");
        if (str != null) {
            temp.info_hash = str;
        }

        temp.address = exchange.getRemoteAddress().getAddress().getHostAddress();

        str = getpar.parameter.get("port");
        if (str != null) {
            temp.port = Integer.parseInt(str);
        }

        str = getpar.parameter.get("uploaded");
        if (str != null) {
            temp.uploaded = Integer.parseInt(str);
        }

        str = getpar.parameter.get("downloaded");
        if (str != null) {
            temp.downloaded = Integer.parseInt(str);
        }

        str = getpar.parameter.get("left");
        if (str != null) {
            temp.left = Integer.parseInt(str);
        }

        return temp;
    }

    public void handle(HttpExchange exchange) throws IOException {
        String requestMethod = exchange.getRequestMethod();

        // Evaluate Timeout Peer
        peerFileList.evaluateTimeoutPeer();

        if (requestMethod.equalsIgnoreCase("GET")) {
            // Set Response Header and Body
            Headers responseHeaders = exchange.getResponseHeaders();
            responseHeaders.set("Content-Type", "text/plain");
            exchange.sendResponseHeaders(200, 0);
            OutputStream responseBody = exchange.getResponseBody();

            // Request query
            String query = exchange.getRequestURI().getRawQuery();
            System.out.println("query " + query);
            Request request = new Request(query);

            PeerFile temp = parseQuery(request, exchange);
            PeerFile peerFile = peerFileList.getPeer(temp.info_hash, temp.address);
            String str = "";
            boolean show_response = false;

            if (request.parameter.get("register") != null) {
                String filename = request.parameter.get("register");
                peerFileList.listFiles.add(new File(filename, temp.address));
                responseBody.write("register success;".getBytes());
                System.out.println("register File " + filename + " " + temp.address);
            } else {
                if (peerFile == null) {
                    System.out.println("Peer not found");
                    str = request.parameter.get("event");
                    if ("started".equals(str)) {
                        System.out.println("Peer started");
                        temp.timeout = System.currentTimeMillis() + timeout;
                        peerFileList.add(temp);
                        show_response = true;
                    } else {
                        System.out.println("Peer not found and else started");
                        responseBody.write(("failure_reason file_not_found_or_not_yet_started;").getBytes());
                    }
                } else {
                    System.out.println("Peer found");
                    str = request.parameter.get("event");
                    if ("stopped".equals(str)) {
                        System.out.println("Peer stopped");
                        peerFileList.delete(peerFile.info_hash, peerFile.address);
                    } else if ("completed".equals(str)) {
                        System.out.println("Peer completed");
                        show_response = true;
                    } else if ("started".equals(str)) {
                        System.out.println("Peer started");
                        responseBody.write(("warning_reason file_has_been_started\n").getBytes());
                        show_response = true;
                    } else {
                        System.out.println("Peer found else");
                        show_response = true;
                    }
                }

                if (show_response) {
                    responseBody.write(("interval " + (timeout - delay) + ";").getBytes());
                    responseBody.write(("complete " + peerFileList.complete(temp.info_hash, temp.address) + ";").getBytes());
                    responseBody.write(("incomplete " + peerFileList.incomplete(temp.info_hash, temp.address) + ";").getBytes());
                    responseBody.write(("peers " + peerFileList.getPeersByInfoHash(temp.info_hash, temp.address)).getBytes());

                    if (peerFile != null) {
                        peerFile.timeout = System.currentTimeMillis() + timeout;
                    } else if (temp != null) {
                        temp.timeout = System.currentTimeMillis() + timeout;
                    }
                }
            }

            responseBody.close();
            System.out.println("close");
        }
    }
}
